package com.open.spring.utils.validate.aop;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.open.spring.utils.validate.ValidateUtils;
import com.open.spring.utils.validate.anno.Regulation;
import com.open.spring.utils.validate.anno.RegulationGroup;

@Component
@Aspect
public class ValidateAop {

	private static Log logger = LogFactory.getLog(ValidateAop.class);

	@Pointcut("@annotation(com.ezgo.um.utils.anno.RegulationGroup)")
	private void pointcut() {
	}

	@Around("pointcut()")
	public Object validateAround(ProceedingJoinPoint pjp) throws Throwable {
		Method method = null;
		RegulationGroup vAnno = null;
		boolean validate = false;
		method = RefIns.getInstance().getMethodByClassAndName(pjp.getTarget().getClass(), pjp.getSignature().getName(),
				pjp.getArgs().length);
		vAnno = (RegulationGroup) RefIns.getInstance().getAnnotationByMethod(method, RegulationGroup.class);
		Object[] args = pjp.getArgs();
		Object arg = args[args.length - 1];
		if (!(arg instanceof HttpServletResponse)) {
			logger.error("**最后的一个参数必须是HttpServletResponse的子类**");
			throw new Exception("**最后的一个参数必须是HttpServletResponse的子类**");
		} else {
			validate = validateField(vAnno.value(), pjp.getArgs(), (HttpServletResponse) arg);
		}
		if (validate) {
			return pjp.proceed();
		} else {
			return null;
		}
	}

	/**
	 * 验证参数是否合法
	 * 
	 * @param response
	 * @throws IOException
	 */
	public boolean validateField(Regulation[] vAnnos, Object[] args, HttpServletResponse response)
			throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException, IOException {
		StringBuilder builder = new StringBuilder("{\"status\":\"400\",\"msg\":\"");
		for (Regulation vAnno : vAnnos) {
			Object arg = null;
			if ("".equals(vAnno.value())) {
				arg = args[vAnno.index()];
			} else {
				arg = getFieldByObjectAndFieldName(args[vAnno.index()], vAnno.value());
			}
			String name = vAnno.name().equals("") ? arg.toString() : vAnno.name();
			if (vAnno.notNull()) { // 判断注解参数是否为true
				if (arg == null) {
					sendResponse(response, builder.append(name + "不允许null\"}").toString());
					logger.error(name + "不允许null");
					return false;
				}
			} else { // 如果该参数能够为空，并且当参数为空时，就不用判断后面的了 ，直接返回true
				if (arg == null)
					return true;
			}

			if (vAnno.maxLen() > 0) { // 判断字符串最大长度
				if (((String) arg).length() > vAnno.maxLen()) {
					sendResponse(response, builder.append(name + "长度不能大于" + vAnno.maxLen() + "\"}").toString());
					logger.error(name + "长度不能大于" + vAnno.maxLen());
					return false;
				}
			}

			if (vAnno.minLen() > 0) { // 判断字符串最小长度
				if (((String) arg).length() < vAnno.minLen()) {
					sendResponse(response, builder.append(name + "长度不能小于" + vAnno.minLen() + "\"}").toString());
					logger.error(name + "长度不能小于" + vAnno.minLen());
					return false;
				}
			}

			if (vAnno.maxVal() != -1) { // 判断数值最大值
				if ((Integer) arg > vAnno.maxVal()) {
					sendResponse(response, builder.append(name + "最大值不能大于" + vAnno.maxVal() + "\"}").toString());
					logger.error(name + "最大值不能大于" + vAnno.maxVal());
					return false;
				}
			}

			if (vAnno.minVal() != -1) { // 判断数值最小值
				if ((Integer) arg < vAnno.minVal()) {
					sendResponse(response, builder.append(name + "最小值不能大小" + vAnno.minVal() + "\"}").toString());
					logger.error(name + "最小值不能小于" + vAnno.minVal());
					return false;
				}
			}

			if (!"".equals(vAnno.regStr())) { // 判断正则
				if (arg instanceof String) {
					if (!((String) arg).matches(vAnno.regStr())) {
						sendResponse(response, builder.append(name + "的正则校验" + vAnno.regStr() + "不通过\"}").toString());
						logger.error(name + "的正则校验" + vAnno.regStr() + "不通过");
						return false;
					}
				} else {
					logger.error(name + "的正则校验" + vAnno.regStr() + "不是字符");
				}
			}
			/**
			 * 校验常见的正则
			 */
			String validateStr = ValidateUtils.validateRegexType(vAnno, arg);
			if (!"".equals(validateStr)) {
				sendResponse(response, builder.append(validateStr).toString());
				logger.error(validateStr);
				return false;
			}

		}
		return true;
	}

	/**
	 * 根据对象和属性名得到 属性
	 */
	public Object getFieldByObjectAndFieldName(Object targetObj, String fieldName) throws SecurityException,
			NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		String tmp[] = fieldName.split("\\.");
		Object arg = targetObj;
		for (int i = 0; i < tmp.length; i++) {
			Method methdo = arg.getClass().getMethod(getGetterNameByFieldName(tmp[i]));
			arg = methdo.invoke(arg);
		}
		return arg;
	}

	/**
	 * 根据属性名 得到该属性的getter方法名
	 */
	public String getGetterNameByFieldName(String fieldName) {
		return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
	}

	public void sendResponse(HttpServletResponse response, String json) throws IOException {
		try {
			OutputStream out = response.getOutputStream();
			PrintWriter pw = new PrintWriter(out);
			pw.print(json);
			pw.flush();
		} catch (IOException e) {
			throw e;
		} catch (Exception e) {
			logger.error("校验参数出错", e);
		}
	}

}
